import Koa from 'koa';
import bodyParser from 'koa-bodyparser';
import cors from '@koa/cors';
import config from './config';
import { initMySQL } from './database/mysql';
import { initRedis } from './database/redis';
import { requestIdMiddleware } from './middleware/requestId';
import { loggerMiddleware } from './middleware/logger';
import { abnormalDetectionMiddleware } from './middleware/abnormalDetection';
import { errorHandlerMiddleware } from './middleware/errorHandler';
import { jsonBodyMiddleware } from './middleware/jsonBody';
import {
  rootPathMiddleware,
  webStaticMiddleware,
  adminStaticMiddleware,
  notFoundMiddleware,
} from './middleware/staticFiles';
import routes, { registerRoutes } from './routes';
import { startupCheck } from './utils/startupCheck';
import { logToDatabase, LogType, LogLevel, consoleLog } from './utils/logger';
import { utils } from './utils/utils';

const app = new Koa();

// Koa 应用事件监听
app.on('error', (err, ctx) => {
  const requestId = ctx?.state?.requestId || utils.generateUUID();
  logToDatabase(
    requestId,
    LogType.KOA,
    LogLevel.ERROR,
    `Koa应用错误: ${err.message}`,
    {
      error: {
        name: err.name,
        message: err.message,
        stack: err.stack,
      },
      context: ctx ? {
        method: ctx.method,
        url: ctx.url,
        status: ctx.status,
      } : null,
    }
  ).catch(() => {});
  consoleLog(
    LogType.KOA,
    LogLevel.ERROR,
    `Koa应用错误: ${err.message}`,
    {
      requestId,
      method: ctx?.method,
      url: ctx?.url,
      error: err,
    }
  );
});

// 初始化数据库连接
initMySQL();
initRedis();

// 全局错误处理（最外层）
app.use(errorHandlerMiddleware);

// CORS
app.use(cors({
  origin: '*',
  allowMethods: ['GET', 'POST', 'PUT', 'DELETE', 'OPTIONS'],
  allowHeaders: ['Content-Type', 'Authorization', 'X-Request-Id'],
}));

// Request ID中间件
app.use(requestIdMiddleware);

// JSON Body解析（需要在日志中间件之前，以便记录请求体）
app.use(bodyParser({
  enableTypes: ['json'],
  jsonLimit: '10mb',
}));

// JSON Body验证中间件
app.use(jsonBodyMiddleware);

// 速率限制中间件已关闭（改为基于日志的异常检测）
// app.use(async (ctx, next) => {
//   if (ctx.path.startsWith('/api/')) {
//     await rateLimitMiddleware(ctx, next);
//   } else {
//     await next();
//   }
// });

// 异常检测中间件（仅对API路由，需要在logger之前注册，但会在logger之后检查状态）
// 这样可以在请求执行前检查冷却状态，在请求执行后检查异常
app.use(async (ctx, next) => {
  if (ctx.path.startsWith('/api/')) {
    await abnormalDetectionMiddleware(ctx, next);
  } else {
    await next();
  }
});

// 日志中间件（放在 bodyParser 之后，确保能获取到请求体）
app.use(loggerMiddleware);

// 静态文件服务中间件（用于前端SPA）
// 1. 根路径处理：默认重定向到 /web/ 路由
app.use(rootPathMiddleware);

// 2. Web 端静态文件服务（支持 SPA 路由 fallback）
app.use(webStaticMiddleware);

// 3. Admin 端静态文件服务（支持 SPA 路由 fallback）
app.use(adminStaticMiddleware);

// 启动服务器
async function startServer() {
  // 记录服务启动开始
  await logToDatabase(
        utils.generateUUID(),
    LogType.KOA,
    LogLevel.INFO,
    'Koa服务启动中...',
    {
      env: config.env,
      port: config.port,
    }
  ).catch(() => {});

  // 先注册所有路由
  consoleLog(LogType.KOA, LogLevel.INFO, '正在注册路由...');
  await registerRoutes();
  consoleLog(LogType.KOA, LogLevel.INFO, '路由注册完成');
  
  // 注册路由到 app（在 registerRoutes 之后，但在启动服务器之前）
  app.use(routes.routes());
  app.use(routes.allowedMethods());
  
  // 404处理（放在最后，在路由之后）
  app.use(notFoundMiddleware);
  
  // 启动前检查服务状态
  await startupCheck();
  
  const PORT = config.port;
  app.listen(PORT, async () => {
    const colors = {
      reset: '\x1b[0m',
      bright: '\x1b[1m',
      dim: '\x1b[2m',
      green: '\x1b[32m',
      cyan: '\x1b[36m',
    };
    
    // 记录服务启动成功
    await logToDatabase(
        utils.generateUUID(),
      LogType.KOA,
      LogLevel.INFO,
      'Koa服务启动成功',
      {
        env: config.env,
        port: PORT,
        host: 'localhost',
      }
    ).catch(() => {});
    
    console.log();
    console.log(colors.green + colors.bright + '🚀 服务器已启动' + colors.reset);
    console.log(colors.dim + '─'.repeat(50) + colors.reset);
    consoleLog(
      LogType.KOA,
      LogLevel.INFO,
      `服务器已启动 - 地址: http://localhost:${PORT} - 环境: ${config.env.toUpperCase()}`
    );
    console.log();
  });
}

// 优雅关闭
process.on('SIGTERM', async () => {
  await logToDatabase(
        utils.generateUUID(),
    LogType.KOA,
    LogLevel.INFO,
    '收到SIGTERM信号，正在关闭服务...',
    {}
  ).catch(() => {});
  process.exit(0);
});

process.on('SIGINT', async () => {
  await logToDatabase(
        utils.generateUUID(),
    LogType.KOA,
    LogLevel.INFO,
    '收到SIGINT信号，正在关闭服务...',
    {}
  ).catch(() => {});
  process.exit(0);
});

process.on('uncaughtException', async (err) => {
  await logToDatabase(
        utils.generateUUID(),
    LogType.KOA,
    LogLevel.ERROR,
    `未捕获的异常: ${err.message}`,
    {
      error: {
        name: err.name,
        message: err.message,
        stack: err.stack,
      },
    }
  ).catch(() => {});
  consoleLog(
    LogType.KOA,
    LogLevel.ERROR,
    `未捕获的异常: ${err.message}`,
    {
      error: err,
    }
  );
  process.exit(1);
});

process.on('unhandledRejection', async (reason: any) => {
  await logToDatabase(
        utils.generateUUID(),
    LogType.KOA,
    LogLevel.ERROR,
    `未处理的Promise拒绝: ${reason?.message || String(reason)}`,
    {
      reason: reason?.toString(),
      stack: reason?.stack,
    }
  ).catch(() => {});
  consoleLog(
    LogType.KOA,
    LogLevel.ERROR,
    `未处理的Promise拒绝: ${reason?.message || String(reason)}`,
    {
      error: reason,
    }
  );
});

// 启动应用
startServer().catch((error) => {
  consoleLog(
    LogType.KOA,
    LogLevel.ERROR,
    `启动失败: ${error?.message || String(error)}`,
    {
      error: error,
    }
  );
  process.exit(1);
});

export default app;

